package com.pphh.demo;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * A simple java crypto util with fixed settings
 *
 * @author huangyinhuang
 * @date 7/27/2018
 */
public class SimpleCryptoUtil {

    public static final String AES_ALGORITHM = "AES";
    public static final String CBC_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
    public static final int KEY_SIZE = 128;
    public static final byte[] IVPARAMETER = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

    public static SecretKey generateAESSecretKey() {
        SecretKey key = null;
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
            keyGenerator.init(KEY_SIZE);
            key = keyGenerator.generateKey();
        } catch (NoSuchAlgorithmException e) {
            System.out.print("Sorry, key generator doesn't support the specified algorithm.");
            e.printStackTrace();
        }
        return key;
    }

    public static SecretKey decodeKey(byte[] keyBase64) {
        Base64.Decoder decoder = Base64.getDecoder();
        return new SecretKeySpec(decoder.decode(keyBase64), AES_ALGORITHM);
    }

    public static byte[] encodeKey(SecretKey key) {
        Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encode(key.getEncoded());
    }

    public static byte[] encrypt(byte[] plainText, SecretKey key) {
        return exchange(plainText, key, IVPARAMETER, Cipher.ENCRYPT_MODE);
    }

    public static byte[] decrypt(byte[] secretText, SecretKey key) {
        return exchange(secretText, key, IVPARAMETER, Cipher.DECRYPT_MODE);
    }

    private static byte[] exchange(byte[] original, SecretKey key, byte[] ivParameter, int mode) {
        byte[] newText = null;

        try {
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter);
            Cipher cipher = Cipher.getInstance(CBC_CIPHER_ALGORITHM);
            cipher.init(mode, key, ivParameterSpec);
            newText = cipher.doFinal(original);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }

        return newText;
    }
}
